#include "engine.h"

#include <string>
using namespace std;


int CenterColor(Rubik &rbk, int face)
{
	int ccolor=rbk.center[face]; //for safety
	return ccolor;
}
int EdgeBuddyColor(Rubik &rbk, int face, int edgeIndex)
{
	int face2=Relation[face][edgeIndex];
	int bcolor=rbk.edge[face2][FindBack(face, edgeIndex)];
	return bcolor;
}

PosPair FindEdge(Rubik &rbk, int color, int cbuddy)
{
	PosPair result={-1,-1};
    for(int i=0;i<6;i++)
    {
       for(int j=0;j<4;j++)
       {
           if(rbk.edge[i][j]==color && EdgeBuddyColor(rbk, i, j)==cbuddy)
           {
               result.face=i;
               result.pos=j;
               return result;
	        }
	   }
	}
	return result;
}

int FindCrossUndone(Rubik &rbk, int face)
{
	for(int i=0;i<4;i++)
	{
		if(rbk.edge[face][i] != CenterColor(rbk, face))
		  return i;
	}
	return -1;
}
string SolveEdge(Rubik &rbk, int face, int edgeIndex)
{
	string result="";
	int cSelf=CenterColor(rbk, face);
	int cBuddy=CenterColor(rbk, Relation[face][edgeIndex]);
	
	PosPair nowPos=FindEdge(rbk, cSelf, cBuddy);
	PosPair nowBuddyPos=FindEdge(rbk, cBuddy, cSelf);
	if(nowPos.face==-1)
	{/*something wrong?  */}
	
	//and then?
	if(nowPos.face==face)  //on the same side
	{	
		char action = FaceMoveNames[nowBuddyPos.face];
		result += action;
		TranslateMove(rbk,action);
	}
	else if(nowPos.face==Relation[face][ID_oppo]) //on the oppo side
	{
		int oppoface=nowPos.face;
		int aim=0;
		for(int i=0;i<4;i++)
		{
			if( CenterColor(rbk, Relation[oppoface][i]) == cBuddy)
			{
				aim=i;
				break;
			}
		}
		int rturns=((aim+4)-nowPos.pos)%4;
		char action =FaceMoveNames[oppoface];
		for(int j=0;j<rturns;j++)
		{
			result+= action;
			TranslateMove(rbk, action);
		}
		char action2= FaceMoveNames[Relation[face][edgeIndex]];
		result += action2;
		TranslateMove(rbk, action2);
	}
	else if(nowBuddyPos.face==face) //on side down
	{
		char action= FaceMoveNames[nowPos.face];
		result += action;
		TranslateMove(rbk,action); 
	}
	else if(nowBuddyPos.face==Relation[face][ID_oppo]) // on side up
	{
		int oppoface=nowBuddyPos.face;
        int aim=0;
        for(int i=0;i<4;i++)
        {
             if( CenterColor(rbk, Relation[oppoface][i]) == cBuddy)
           {
                aim=i;
               break;
           }
       }
	     int rturns=((aim+4)-nowBuddyPos.pos)%4;
		 char action =FaceMoveNames[oppoface];
		 for(int j=0;j<rturns;j++)
		{
			 result+= action;
			TranslateMove(rbk, action);
		 }
		char action2= FaceMoveNames[Relation[face][edgeIndex]];
		result += action2;
		TranslateMove(rbk, action2);
	}
	//re do
	nowPos=FindEdge(rbk, cSelf, cBuddy);
	nowBuddyPos=FindEdge(rbk, cBuddy, cSelf);
	char action1;
	if( CenterColor(rbk, Relation[nowPos.face][EdgeEdgeL[nowPos.pos]] )==cSelf )
	  action1=FaceMoveNames[nowBuddyPos.face];
	else
	  action1=FaceCounterMoveNames[nowBuddyPos.face];
	
	int aim=0;
	for(int i=0;i<4;i++)
	{
		if( Relation[face][i]==nowBuddyPos.face)
		{
			aim=i;
			break;
		}
	}
	char action2=FaceMoveNames[face];
	char action3=FaceCounterMoveNames[face];
	int rturns=((aim+4)-edgeIndex)%4;
	for (int j=0; j<rturns;j++)
	{
		result += action2;
		TranslateMove(rbk, action2);
	}
	result+= action1;
	TranslateMove(rbk, action1);
	for (int j=0;j<rturns;j++)
	{
		result+=action3;
		TranslateMove(rbk, action3);
	}
		
	return result;
}

string SolveDCross(Rubik &rbk)
{
	string result="";
	int i;
	while(( i = FindCrossUndone(rbk, D) )!=-1)
	{
		result += SolveEdge(rbk, D,i); 
	}
	return result;
}
string SolveDCorner(Rubik &rbk)
{
	string result;
	return result;
}
string SolveSecondLayer(Rubik &rbk)
{
	    string result;
		    return result;
}
string SolveUCross(Rubik &rbk)
{
	    string result;
		    return result;
}
string SolveUCornerNoDirection(Rubik &rbk)
{
	    string result;
		    return result;
}
string SolveDirection(Rubik &rbk)
{
	string result;
	    return result;
}


string SolveRubik(Rubik &rbk)
{
	Rubik rbk2;
	CopyRubik(rbk, rbk2);
	string initPosition = RubikToString(rbk2);
	string solution="";
	
	solution += SolveDCross(rbk2);
	

	cout<<initPosition<<endl;
	cout<<solution<<endl;
	return solution;
}

